import Bxios from './bxios'
import { TOKEN_DEL_KEY } from '@/utils/tokenConfig'
import storage from '@/utils/storage'
import { GrantType } from '@/apis/sign/type'
import { signByUser } from '@/apis/sign'
import { TOKEN_OVERDUE } from './bxios.type'
import { useShopInfoStore } from '@/store/modules/shopInfo'

type Method = 'get' | 'post' | 'put' | 'delete'

// 老token
const shopInfo = storage.get('shopStore') as any
const bxios = new Bxios({
    baseUrl: import.meta.env.VITE_BASE_URL,
    header: {
        'Device-Id': uni.getSystemInfoSync().deviceId,
        'Client-Type': import.meta.env.VITE_CLIENT_TYPE,
        'Content-Type': 'application/json',
        'Shop-Id': 0,
        'Accept-Language': import.meta.env.VITE_ACCEPT_LANGUAGE,
        // #ifdef H5
        Platform: 'H5',
        // #endif
        // #ifdef MP-WEIXIN
        //@ts-ignore
        Platform: 'WECHAT_MINI_APP',
        // #endif
        // #ifdef APP-PLUS
        //@ts-ignore
        Platform: 'ANDROID',
        // #endif
    },
})
let requests: any[] = []
const whiteList = ['/gruul-mall-uaa/login?grant_type=refresh_token']
const notNeedTokenList = ['gruul-mall-uaa/uaa/auth/captcha/slider', 'gruul-mall-uaa/uaa/auth/captcha/sms', 'gruul-mall-uaa/login?grant_type=sms_code']

bxios.interceptors.request.use(
    (config) => {
        // 如果正在刷新中
        if (storage.get('isRefreshing') && !whiteList.includes(config.url)) {
            return new Promise((resolve) => {
                requests.push((token: string) => {
                    config.header.Authorization = token
                    resolve(config)
                })
            })
        }

        const newShopInfo = storage.get('shopStore')
        const { token, id } = newShopInfo || { token: null }
        if (token) {
            if (!notNeedTokenList.includes(config.url)) {
                config.header.Authorization = token
            }
        } else {
            delete config.header.Authorization
        }
        if (id) {
            config.header['Shop-Id'] = id
        }
        return Promise.resolve(config)
    },
    (err) => {
        return Promise.reject(err)
    },
)
bxios.interceptors.response.use(
    async ({ data, config }) => {
        const res = data
        const { code, msg } = res
        if (TOKEN_OVERDUE.includes(code)) {
            uni.$emit(TOKEN_DEL_KEY)
            return Promise.reject(res)
        }
        if (code === 4) {
            // 无感刷新
            if (!storage.get('isRefreshing')) {
                storage.set('isRefreshing', true, 30)
                const refresh_token = storage.get('shopStore')?.refresh_token
                try {
                    const { data } = await signByUser(GrantType.REFRESH_TOKEN, { value: refresh_token })
                    const newToken = data?.value as string
                    if (!newToken) {
                        storage.set('isRefreshing', false, 30)
                        uni.$emit(TOKEN_DEL_KEY)
                        return Promise.reject('token刷新失败')
                    }
                    storage.set(
                        'shopStore',
                        {
                            ...shopInfo,
                            token: data?.value,
                            refresh_token: data?.refreshToken.value,
                        },
                        30,
                    )
                    useShopInfoStore().SET_SHOP_INFO(shopInfo)
                    useShopInfoStore().SET_SHOP_TOKEN({ access_token: data!.value || '', refresh_token: data!.refreshToken.value || '' })
                    useShopInfoStore().SET_SHOP_Id(data!.open.shopId as string)

                    requests.forEach((cb: (t: string) => any) => {
                        cb(newToken)
                    })
                    requests = []
                    storage.set('isRefreshing', false, 30)
                    config.header.Authorization = newToken
                    // config.method转小写
                    const method = config.method.toLowerCase() as Method
                    return Promise.resolve(bxios[method](config.url, config.data, config))
                } catch (error) {
                    storage.set('isRefreshing', false, 30)
                    console.log('error', error)
                    return Promise.reject(error)
                }
            }
            return new Promise((resolve) => {
                requests.push((token: string) => {
                    config.header.Authorization = token
                    // config.method转小写
                    const method = config.method.toLowerCase() as Method
                    resolve(bxios[method](config.url, config.data, config))
                })
            })
        }

        return Promise.resolve(res)
    },
    (err) => {
        uni.showToast({
            icon: 'none',
            title: `${err || '服务器内部错误'}`,
        })
        return Promise.reject(err)
    },
)

export default bxios
